package com.vader.boot.beanPostProcessor;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.StandardEnvironment;

import javax.management.StandardEmitterMBean;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author Vader
 * @date 2022/5/13
 **/
@Slf4j
public class DigInAutowired {
    public static void main(String[] args) throws Throwable {
        DefaultListableBeanFactory be = new DefaultListableBeanFactory();
        be.registerSingleton("bean2", new Bean2());
//        be.registerSingleton("bean3", new Bean3());
        be.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        be.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);

        AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
        CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor = new CommonAnnotationBeanPostProcessor();
        autowiredAnnotationBeanPostProcessor.setBeanFactory(be);
        Bean1 bean1 = new Bean1();
        log.info("bean1:{}", bean1);
//        autowiredAnnotationBeanPostProcessor.postProcessProperties(null, bean1, "bean1");
        log.info("bean1:{}", bean1);

        Method findAutowiringMetadata = autowiredAnnotationBeanPostProcessor.getClass()
                .getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadata.setAccessible(true);
        InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata.invoke(autowiredAnnotationBeanPostProcessor, "bean1", Bean1.class, null);
        log.info("find_bean1:{}", JSONObject.toJSONString(metadata));

        //通过inject依赖注入
        metadata.inject(bean1, "bean1", null);
        log.info("bean1:{}", bean1);

        //通过类型查找参数
        Field bean3 = Bean1.class.getDeclaredField("bean3");
        DependencyDescriptor descriptor1 = new DependencyDescriptor(bean3, false);
        Object doBean3 = be.doResolveDependency(descriptor1, null, null, null);
        log.info("dp1_bean3:{}", JSONObject.toJSONString(doBean3));

        Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
        DependencyDescriptor descriptor2 = new DependencyDescriptor(new MethodParameter(setBean2,0), false);
        Object doSetBean2 = be.doResolveDependency(descriptor2, null, null, null);
        log.info(doSetBean2.toString());

        Method setHome = Bean1.class.getDeclaredMethod("setHome", String.class);
        DependencyDescriptor descriptor3 = new DependencyDescriptor(new MethodParameter(setHome,0), false);
        Object doSetHome = be.doResolveDependency(descriptor3, null, null, null);
        log.info(doSetHome.toString());
    }
}
